﻿// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
// (“Fluent UI”)。该示例仅供参考，
// 用以补充《Microsoft 基础类参考》和
// MFC C++ 库软件随附的相关电子文档。
// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
// 若要了解有关 Fluent UI 许可计划的详细信息，请访问
// https://go.microsoft.com/fwlink/?LinkId=238214.
//
// 版权所有(C) Microsoft Corporation
// 保留所有权利。

// MainFrm.cpp: CMainFrame 类的实现
//

#include "pch.h"
#include "framework.h"
#include "DBBrowser.h"
#include "DBBrowserDoc.h"

#include "MainFrm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CMainFrame

IMPLEMENT_DYNCREATE(CMainFrame, CFrameWndEx)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)
	ON_WM_CREATE()
	ON_WM_GETMINMAXINFO()
	ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnApplicationLook)
	ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnUpdateApplicationLook)
	ON_UPDATE_COMMAND_UI(ID_FILE_PRINT_PREVIEW, &CMainFrame::OnUpdateFilePrintPreview)
	ON_WM_CLOSE()
	ON_UPDATE_COMMAND_UI_RANGE(ID_WEIGHTGEN, ID_CLEARUP, &CMainFrame::OnUpdateQuickOperate)
	ON_COMMAND_RANGE(ID_WEIGHTGENDESC, ID_WEIGHTGEN, &CMainFrame::OnWeightGen)
	ON_COMMAND(ID_VACUUM, &CMainFrame::OnVacuum)
	ON_COMMAND_RANGE(ID_CLEARUP, ID_HOLDMIN, &CMainFrame::OnClearup)
	ON_WM_COPYDATA()
END_MESSAGE_MAP()

// CMainFrame 构造/析构

CMainFrame::CMainFrame() noexcept
{
	// TODO: 在此添加成员初始化代码
	theApp.m_nAppLook = theApp.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_OFF_2007_BLUE);
}

CMainFrame::~CMainFrame()
{
}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFrameWndEx::OnCreate(lpCreateStruct) == -1)
		return -1;

	m_wndRibbonBar.Create(this);
	m_wndRibbonBar.LoadFromResource(IDR_RIBBON);

	if (!m_wndStatusBar.Create(this))
		return -1;

	m_wndStatusBar.AddElement(new CMFCRibbonStatusBarPane(1112, (L"ver：" + ((CDBBrowserApp*)AfxGetApp())->GetAppVersion() 
		+ (sizeof(char*) == 8 ? L" 64bit" : L" 32bit")).data(), FALSE, NULL, L"ver:99.99.99.99 64bit"), _T("版本"));
	m_wndStatusBar.AddSeparator();
	m_wndStatusBar.AddElement(new CMFCRibbonProgressBar(ID_STATUSBAR_PROGRESS, 200), _T("进度条"));
	m_wndStatusBar.AddElement(new CMFCRibbonStatusBarPane(ID_STATUSBAR_PANE1, _T(" "), FALSE, NULL, _T("剩余时间：xx分xx秒xxx毫秒")), _T("剩余用时"));
	m_wndStatusBar.AddExtendedElement(new CMFCRibbonStatusBarPane(ID_STATUSBAR_PANE2, _T(" "), FALSE, NULL, _T("共9,9999,9999条")), _T("记录数"));

	//分隔符
	//m_wndStatusBar.AddSeparator();
	
	// 启用 Visual Studio 2005 样式停靠窗口行为
	CDockingManager::SetDockingMode(DT_SMART);
	// 启用 Visual Studio 2005 样式停靠窗口自动隐藏行为
	EnableAutoHidePanes(CBRS_ALIGN_ANY);

	// 加载菜单项图像(不在任何标准工具栏上): 
	CMFCToolBar::AddToolBarForImageCollection(IDR_MENU_IMAGES, theApp.m_bHiColorIcons ? IDB_MENU_IMAGES_24 : 0);

	// 创建停靠窗口
	if (!CreateDockingWindows())
	{
		TRACE0("未能创建停靠窗口\n");
		return -1;
	}

	DockPane(&m_wndClassView);

	m_wndRichEdit.EnableDocking(CBRS_ALIGN_ANY);
	DockPane(&m_wndRichEdit);

	// 基于持久值设置视觉管理器和样式
	OnApplicationLook(theApp.m_nAppLook);
	return 0;
}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !CFrameWndEx::PreCreateWindow(cs) )
		return FALSE;
	// TODO: 在此处通过修改
	WNDCLASS wndclass;
	::GetClassInfo(AfxGetInstanceHandle(), cs.lpszClass, &wndclass);
	wndclass.lpszClassName = _T("Yzime");
	wndclass.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	AfxRegisterClass(&wndclass);
	cs.lpszClass = _T("Yzime");
	return TRUE;
}

BOOL CMainFrame::CreateDockingWindows()
{
	BOOL bNameValid;

	// 创建类视图
	CString strClassView;
	bNameValid = strClassView.LoadString(IDS_CLASS_VIEW);
	ASSERT(bNameValid);
	EnableLoadDockState(FALSE);
	if (!m_wndClassView.Create(strClassView, this, CRect(0, 0, 200, 200), TRUE, ID_VIEW_CLASSVIEW, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
	{
		TRACE0("未能创建“类视图”窗口\n");
		return FALSE; // 未能创建
	}

	//m_wndClassView.SetControlBarStyle(~AFX_CBRS_CLOSE);
	m_wndClassView.SetControlBarStyle(AFX_CBRS_RESIZE);
	
	m_wndRichEdit.Create(L"编辑单元格", this, CRect(0, -200, 200, 0), TRUE, ID_RICH_PANE, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_RIGHT | CBRS_FLOAT_MULTI);
	m_wndRichEdit.SetControlBarStyle(AFX_CBRS_RESIZE);
	
	SetDockingWindowIcons(theApp.m_bHiColorIcons);
	return TRUE;
}

void CMainFrame::SetDockingWindowIcons(BOOL bHiColorIcons)
{
	HICON hClassViewIcon = (HICON) ::LoadImage(::AfxGetResourceHandle(), MAKEINTRESOURCE(bHiColorIcons ? IDI_CLASS_VIEW_HC : IDI_CLASS_VIEW), IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), 0);
	m_wndClassView.SetIcon(hClassViewIcon, FALSE);
}

// CMainFrame 诊断

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
	CFrameWndEx::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
	CFrameWndEx::Dump(dc);
}
#endif //_DEBUG


// CMainFrame 消息处理程序

void CMainFrame::OnApplicationLook(UINT id)
{
	CWaitCursor wait;

	theApp.m_nAppLook = id;

	switch (theApp.m_nAppLook)
	{
	case ID_VIEW_APPLOOK_WIN_2000:
		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManager));
		m_wndRibbonBar.SetWindows7Look(FALSE);
		break;

	case ID_VIEW_APPLOOK_OFF_XP:
		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP));
		m_wndRibbonBar.SetWindows7Look(FALSE);
		break;

	case ID_VIEW_APPLOOK_WIN_XP:
		CMFCVisualManagerWindows::m_b3DTabsXPTheme = TRUE;
		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
		m_wndRibbonBar.SetWindows7Look(FALSE);
		break;

	case ID_VIEW_APPLOOK_OFF_2003:
		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003));
		CDockingManager::SetDockingMode(DT_SMART);
		m_wndRibbonBar.SetWindows7Look(FALSE);
		break;

	case ID_VIEW_APPLOOK_VS_2005:
		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005));
		CDockingManager::SetDockingMode(DT_SMART);
		m_wndRibbonBar.SetWindows7Look(FALSE);
		break;

	case ID_VIEW_APPLOOK_VS_2008:
		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2008));
		CDockingManager::SetDockingMode(DT_SMART);
		m_wndRibbonBar.SetWindows7Look(FALSE);
		break;

	case ID_VIEW_APPLOOK_WINDOWS_7:
		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows7));
		CDockingManager::SetDockingMode(DT_SMART);
		m_wndRibbonBar.SetWindows7Look(TRUE);
		break;

	default:
		switch (theApp.m_nAppLook)
		{
		case ID_VIEW_APPLOOK_OFF_2007_BLUE:
			CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);
			break;

		case ID_VIEW_APPLOOK_OFF_2007_BLACK:
			CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack);
			break;

		case ID_VIEW_APPLOOK_OFF_2007_SILVER:
			CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver);
			break;

		case ID_VIEW_APPLOOK_OFF_2007_AQUA:
			CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua);
			break;
		}

		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));
		CDockingManager::SetDockingMode(DT_SMART);
		m_wndRibbonBar.SetWindows7Look(FALSE);
	}

	RedrawWindow(nullptr, nullptr, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW | RDW_FRAME | RDW_ERASE);

	theApp.WriteInt(_T("ApplicationLook"), theApp.m_nAppLook);
}


void CMainFrame::OnUpdateApplicationLook(CCmdUI* pCmdUI)
{
	pCmdUI->SetRadio(theApp.m_nAppLook == pCmdUI->m_nID);
}

void CMainFrame::OnUpdateFilePrintPreview(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(IsPrintPreview());
}

void CMainFrame::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	lpMMI->ptMinTrackSize.x = 800;
	lpMMI->ptMinTrackSize.y = 600;
	CFrameWndEx::OnGetMinMaxInfo(lpMMI);
}

void CMainFrame::OnClose()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)GetActiveDocument();
	if (pDoc->m_transaction) {
		int ret = AfxMessageBox(L"事务未提交，是否提交？", 4, 0);
		if (ret == IDYES) {
			try {
				pDoc->m_db << "commit;";
			}
			catch (sqlite::sqlite_exception& e) {
				MessageBoxA(*AfxGetApp()->m_pMainWnd, e.get_msg(), 0, 0);
				return;
			}
		}
	}
	CFrameWndEx::OnClose();
}


void CMainFrame::OnUpdateQuickOperate(CCmdUI *pCmdUI)
{
	// TODO: 在此添加命令处理程序代码
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)GetActiveDocument();
	if (!pDoc) { return; }
	if (!pDoc->m_db.connection()) {
		pCmdUI->Enable(FALSE);
	}
	else {
		switch (pCmdUI->m_nID)
		{
		case ID_VACUUM:
			pCmdUI->Enable(!pDoc->m_transaction);
			break;
		case ID_CLEARUP:
			pCmdUI->Enable(pDoc->m_table != _T(""));
			break;
		case ID_WEIGHTGEN:
			pCmdUI->Enable(pDoc->m_table != _T(""));
			break;
		default:
			break;
		}
	}
}


void CMainFrame::OnWeightGen(UINT nID)
{
	// TODO: 在此添加命令处理程序代码
	auto pStatusBar = (CMFCRibbonStatusBar*)GetPane(AFX_IDW_STATUS_BAR);
	auto pProgressBar = (CMFCRibbonProgressBar*)(pStatusBar->FindElement(ID_STATUSBAR_PROGRESS));
	auto pT = pStatusBar->FindElement(ID_STATUSBAR_PANE1);
	pProgressBar->SetPos(0); pT->SetText(L"执行中..."), pT->Redraw();
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)GetActiveDocument();
	CString sql;
	std::wcmatch res;
	std::regex_match(pDoc->m_table.GetString(), res, std::wregex(L"^([^\\.]+\\.)?'?([^\\.]+?)'?$"));
	CString d = std::wstring(res[1].first, res[1].second).data();
	CString t = std::wstring(res[2].first, res[2].second).data();
	sql.Format(_T("PRAGMA %stable_info('%s')"), d, t);
	std::wstring lastzd;
	pDoc->m_db << sql >> [&](std::wstring cid, std::wstring name) { lastzd = name; };
	try {
		if (pDoc->m_autotrans && !pDoc->m_transaction) {
			pDoc->m_db << "begin;";
			pDoc->m_transaction = true;
		}
		sql.Format(_T("select type,name from %ssqlite_master where type = 'index' and tbl_name = '%s'"), d, t);
		bool hasindex = false;
		pDoc->m_db << sql >> [&](std::wstring type, std::wstring name) {
			sql.Format(_T("PRAGMA %sindex_info('%s')"), d, name.data());
			pDoc->m_db << sql >> [&](std::wstring s1, std::wstring s2, std::wstring s3) { if (s3 == L"key") { hasindex = true; } };
		};
		if (!hasindex) {
			sql.Format(_T("create index %s'sy_%s' on '%s'('key')"), d, t + (t.Find(_T("pinyin")) != -1 ? _T("____") : _T("")), t);
			pDoc->m_db << sql;
		}
		sql.Format(_T("UPDATE %s as b SET %s=(SELECT count(*) FROM %s a WHERE a.key=b.key AND a.ROWID%c=b.ROWID)"),
			pDoc->m_table, lastzd.data(), pDoc->m_table, nID == ID_WEIGHTGEN ? _T('>') : _T('<'));
		pDoc->m_db << sql;
		if (!hasindex && t.Find(_T("pinyin")) != -1) { pDoc->m_db << L"drop index 'sy_pinyin____'"; }
		pDoc->databaseadapter(pDoc->m_sql, false);
		((CClassView*)GetPane(ID_VIEW_CLASSVIEW))->ReBuildTree();
	}
	catch (sqlite::sqlite_exception& e) {
		MessageBoxA(*this, e.get_msg(), 0, 0);
	}
	pT->SetText(L""), pT->Redraw();
	pProgressBar->SetPos(100);
}


void CMainFrame::OnVacuum()
{
	// TODO: 在此添加命令处理程序代码
	auto pProgressBar = (CMFCRibbonProgressBar*)(((CMFCRibbonStatusBar*)GetPane(AFX_IDW_STATUS_BAR))->FindElement(ID_STATUSBAR_PROGRESS));
	pProgressBar->SetPos(0);
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)GetActiveDocument();
	std::wcmatch res;
	std::regex_match(pDoc->m_table.GetString(), res, std::wregex(L"^([^\\.]+)\\.'?([^\\.]+?)'?$"));
	pDoc->m_db << L"VACUUM " + std::wstring(res[1].first, res[1].second);
	pProgressBar->SetPos(100);
}



void CMainFrame::OnClearup(UINT nID)
{
	// TODO: 在此添加命令处理程序代码
	CDBBrowserDoc *pDoc = (CDBBrowserDoc*)GetActiveDocument();
	auto pStatusBar = (CMFCRibbonStatusBar*)GetPane(AFX_IDW_STATUS_BAR);
	auto pProgressBar = (CMFCRibbonProgressBar*)(pStatusBar->FindElement(ID_STATUSBAR_PROGRESS));
	auto pT = pStatusBar->FindElement(ID_STATUSBAR_PANE1);
	pProgressBar->SetPos(0); pT->SetText(L"执行中..."), pT->Redraw();
	CString sql;
	std::wcmatch res;
	std::regex_match(pDoc->m_table.GetString(), res, std::wregex(L"^([^\\.]+\\.)?'?([^\\.]+?)'?$"));
	CString d = std::wstring(res[1].first, res[1].second).data();
	CString t = std::wstring(res[2].first, res[2].second).data();
	std::vector<std::wstring> info;
	sql.Format(_T("select sql from %ssqlite_master where tbl_name = '%s' order by type desc"), d, t);
	try {
		pDoc->m_db << sql >> [&](std::wstring s) { info.push_back(s); };
		if (!info.size())
			return;
		sql.Format(_T("PRAGMA %stable_info('%s')"), d, t);
		CString sel, group;
		pDoc->m_db << sql >> [&](std::wstring s1, std::wstring s2, std::wstring s3) {
			if (s2 == L"weight") {
				sel += L","; sel += (nID == ID_HOLDMIN ? L"min" : nID == ID_HOLDSUM ? L"sum" : L"max"); sel += "(weight)";
			}
			else { sel += (L"," + s2).data(); }
			if (!std::regex_match(s2, std::wregex(L"weight|comment", std::wregex::icase))) { group += (L"," + s2).data(); }
		};
		sel.Delete(0, 1); group.Delete(0, 1);
		CString ntb = d + _T("'hebing'");
		if (pDoc->m_autotrans && !pDoc->m_transaction) {
			pDoc->m_db << "begin;";
			pDoc->m_transaction = true;
		}
		pDoc->m_db << L"drop table if exists " + ntb;
		std::wstring tt = pDoc->GetDefaultCreateSQL(t, false);
		if (!tt.empty())
			info[0] = tt;
		std::wstring nsql = std::regex_replace(info[0], std::wregex(L"^\\s*create\\s+table\\s+.+?\\(", std::wregex::icase), (L"create table " + ntb + L" (").GetString());
		pDoc->m_db << nsql;
		sql.Format(_T("insert into %s select %s from %s group by %s "), ntb, sel, pDoc->m_table, group);
		pDoc->m_db << sql;
		pDoc->m_db << L"drop table " + pDoc->m_table;
		sql.Format(_T("alter table %s rename to '%s';"), ntb, t);
		pDoc->m_db << sql;
		for (size_t i = 1; i < info.size(); i++) {
			pDoc->m_db << std::regex_replace(info[i], std::wregex(L"(create\\s+index\\s+)", std::wregex::icase), (L"$1" + d).GetString());
		}
		pDoc->databaseadapter(pDoc->m_sql, false);
		((CClassView*)GetPane(ID_VIEW_CLASSVIEW))->ReBuildTree();
	}
	catch (sqlite::sqlite_exception& e) {
		MessageBoxA(*this, e.get_msg(), 0, 0);
	}
	pT->SetText(L""), pT->Redraw();
	pProgressBar->SetPos(100);
}


BOOL CMainFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (!pCopyDataStruct || !init)
		return FALSE;
	std::wstring data = (LPTSTR)pCopyDataStruct->lpData;
	auto pDoc = (CDBBrowserDoc*)GetActiveDocument();
	int fg = pCopyDataStruct->dwData;
	if (fg == 1) {
		((CDBBrowserApp*)AfxGetApp())->SelectNode(data.data());
		return TRUE;
	}
	else if (fg == 2) {
		if (!pDoc->m_codegen || pDoc->m_codegen->GetDict()->Find("@rules")) { }
		else if (data == L"pinyin") {
			pDoc->m_codegen->SetMode("pinyin");
		}
		else if (data == L"wubi")
			pDoc->m_codegen->SetMode("wubi");
		else if (data == L"zhengma")
			pDoc->m_codegen->SetMode("zhengma");
		else
			pDoc->m_codegen->SetCustomRules(data);
		return TRUE;
	}
	else if (fg == 3) {
		bool isBuiltin = true;
		std::wstring m_exepath = ((CDBBrowserApp*)AfxGetApp())->m_exepath;
		CString mbfile;
		mbfile.Format(_T("%sData\\@mb_%s.txt"), m_exepath.data(), data.data());
		if (std::regex_search(data, std::wregex(L"pinyin", std::wregex::icase))) {
			pDoc->LoadDictFromRes(IDR_DICT_PINYIN);
			pDoc->m_codegen->SetMode("pinyin");
			if (PathFileExistsW(mbfile))
				pDoc->m_codegen->GetDict()->LoadDict((TCHAR*)mbfile.GetString());
			pDoc->m_codegen->JiebaInit(pDoc->GetJieba());
		}
		else if (std::regex_search(data, std::wregex(L"zhengma|郑码", std::wregex::icase))) {
			pDoc->LoadDictFromRes(IDR_DICT_ZHENGMA);
			pDoc->m_codegen->SetMode("zhengma");
			if (PathFileExistsW(mbfile))
				pDoc->m_codegen->GetDict()->LoadDict((TCHAR*)mbfile.GetString());
		}
		else if (std::regex_search(data, std::wregex(L"wubi|wb|五笔", std::wregex::icase))
			&& std::regex_search(data, std::wregex(L"98|86|九八|八六", std::wregex::icase))) {
			pDoc->LoadDictFromRes(std::regex_search(data, std::wregex(L"98|九八")) ? IDR_DICT_WB98 : IDR_DICT_WB86);
			pDoc->m_codegen->SetMode("wubi");
			if (PathFileExistsW(mbfile))
				pDoc->m_codegen->GetDict()->LoadDict((TCHAR*)mbfile.GetString());
		}
		else {
			isBuiltin = false;
			if (pDoc->m_codegen)
				delete pDoc->m_codegen, pDoc->m_codegen = nullptr;
			if (!PathFileExistsW(mbfile))
				mbfile = (m_exepath + L"Data\\@mb.txt").data();
			if (!std::regex_search(data, std::wregex(L"english|hotstrings|functions|cliphistory|customs|symbol", std::wregex::icase)) && PathFileExistsW(mbfile))
				pDoc->m_codegen = new Hanzi::CodeGenerater((TCHAR*)mbfile.GetString());
		}
		if (isBuiltin) {
			std::unordered_map<std::string, Hanzi::Codes>::iterator it;
			if (pDoc->m_codegen->GetDict()->Find("@rules", it))
				pDoc->m_codegen->SetCustomRules(it->second[0]);
		}
		return TRUE;
	}
	else if (fg == 0 && pDoc->m_codegen) {
		data = pDoc->m_codegen->GetCode(data)[0];
		::SendMessage(pWnd->m_hWnd, WM_SETTEXT, (WPARAM)m_hWnd, (LPARAM)data.data());
		if (!IsWindowVisible())
			((CDBBrowserView*)GetActiveView())->SetTimer(999, 120000, 0);
		return TRUE;
	}
	return CFrameWndEx::OnCopyData(pWnd, pCopyDataStruct);
}
